package com.ruicar.afs.cloud.basic.clearance.controller;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.ruicar.afs.cloud.basic.clearance.condition.CalSettleCondition;
import com.ruicar.afs.cloud.basic.clearance.condition.QueryApplyNoCondition;
import com.ruicar.afs.cloud.basic.common.condition.PrepaymentRecordQueryCondition;
import com.ruicar.afs.cloud.basic.common.entity.*;
import com.ruicar.afs.cloud.basic.common.mapper.BasicMainInfoMapper;
import com.ruicar.afs.cloud.basic.common.service.*;
import com.ruicar.afs.cloud.basic.common.vo.SettleResultVo;
import com.ruicar.afs.cloud.basic.common.vo.SettleStayVo;
import com.ruicar.afs.cloud.batch.entity.AfsBatchInfo;
import com.ruicar.afs.cloud.batch.service.AfsBatchInfoService;
import com.ruicar.afs.cloud.common.core.constant.CommonConstants;
import com.ruicar.afs.cloud.common.core.query.QueryCondition;
import com.ruicar.afs.cloud.common.core.util.IResponse;
import com.ruicar.afs.cloud.common.modules.contract.enums.*;
import com.ruicar.afs.cloud.common.util.EmptyUtils;
import com.ruicar.afs.cloud.common.vo.StaySettleVo;
import com.ruicar.afs.cloud.manage.api.dto.ImmunityDto;
import com.ruicar.afs.cloud.manage.api.dto.PrepaymentRecordDto;
import com.ruicar.afs.cloud.manage.api.feign.cust.CustChangeFeign;
import com.ruicar.afs.cloud.manage.api.feign.immunity.ImmunityFeign;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author: yaorui.zhang
 * @date: 2020年6月18日 18:05:25
 * @description: 待结清查询使用
 */
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/staySettle")
public class StaySettleController {

    private final BasicMainInfoMapper basicMainInfoMapper;
    private final BasicMainInfoService basicMainInfoService;
    private final BasicRepaymentPlanService basicRepaymentPlanService;
    private final BasicChannelInfoService basicChannelInfoService;
    private final BasicFinancialAgreementService basicFinancialAgreementService;
    private final BasicPenaltyInterestService basicPenaltyInterestService;
    private final BasicExpenseRecordService basicExpenseRecordService;
    private final BasicExpenseRecordDetailService basicExpenseRecordDetailService;
    private final ImmunityFeign immunityFeign;
    private final CustChangeFeign custChangeFeign;
    private final BasicCustBaseInfoService basicCustBaseInfoService;
    private final BasicContractCustRelationService basicContractCustRelationService;
    private final BasicProductParamService basicProductParamService;
    private final AfsBatchInfoService afsBatchInfoService;
    private final BasicReceiptRecordService basicReceiptRecordService;

    @PostMapping(value = "/getPrepaymentRecordByContractNos")
    @ApiOperation(value = "查询已存在提前结清申请记录的合同")
    public IResponse<List<PrepaymentRecordDto>> getPrepaymentRecordByContractNos(@RequestBody PrepaymentRecordQueryCondition condition) {
        if (EmptyUtils.isEmpty(condition.getContractNo()) && EmptyUtils.isEmpty(condition.getCertNo())) {
            return IResponse.fail("证件号或合同号，必须要传值其中的一项");
        }

        List<String> contractNoList = new ArrayList<>();
        if (EmptyUtils.isNotEmpty(condition.getCertNo())) {
            List<BasicCustBaseInfo> custPersonalDetails = basicCustBaseInfoService.list(Wrappers.<BasicCustBaseInfo>query().lambda()
                    .eq(BasicCustBaseInfo::getCertNo, condition.getCertNo())
            );
            if (EmptyUtils.isNotEmpty(custPersonalDetails)) {
                List<String> custNos = custPersonalDetails.stream().map(BasicCustBaseInfo::getCustNo).collect(Collectors.toList());
                List<BasicContractCustRelation> relationList = basicContractCustRelationService.list(Wrappers.<BasicContractCustRelation>query().lambda()
                        .in(BasicContractCustRelation::getCustNo, custNos)
                        .eq(BasicContractCustRelation::getCustRole, PersonRoleTypeEnum.MAIN_PERSON)
                );
                if (EmptyUtils.isNotEmpty(relationList)) {
                    relationList.forEach(relation -> {
                        contractNoList.add(relation.getContractNo());
                    });
                }
            }
        }
        if (EmptyUtils.isEmpty(condition.getCertNo()) && EmptyUtils.isNotEmpty(condition.getContractNo())) {
            contractNoList.add(condition.getContractNo());
        }
        String contractNos = "";
        if (EmptyUtils.isNotEmpty(contractNoList)) {
            contractNos = StringUtils.join(contractNoList.toArray(), ",");
        }
        List<PrepaymentRecordDto> prepaymentRecordDtoList = new ArrayList<>();

        IResponse<List<PrepaymentRecordDto>> iResponse = custChangeFeign.getPrepaymentRecordByContractNos(contractNos);
        if (CommonConstants.SUCCESS.equals(iResponse.getCode())) {
            prepaymentRecordDtoList = iResponse.getData();
        }
        return IResponse.success(prepaymentRecordDtoList);
    }

    @PostMapping(value = "/getStaySettleApplyNoList")
    @ApiOperation(value = "多条件分页获取待结清申请编号")
    public IResponse<List<QueryApplyNoCondition>> getStaySettleApplyNoList() {
        //查询出所有合同生效的单子
        List<BasicMainInfo> list = basicMainInfoService.list(Wrappers.<BasicMainInfo>query().lambda()
                .eq(BasicMainInfo::getContractStatus, ContractStatusEnum.contractEffective)
        );
        //查询的合同转换为前端list列表
        List<QueryApplyNoCondition> voList = Lists.transform(list, (entity) -> {
            QueryApplyNoCondition vo = new QueryApplyNoCondition();
            vo.setTitle(entity.getApplyNo());
            vo.setValue(entity.getApplyNo());
            return vo;
        });
        return IResponse.success(voList);
    }

    @PostMapping(value = "/getStaySettleDetailByApplyNo")
    @ApiOperation(value = "根据申请编号获取详情")
    public IResponse<SettleStayVo> getStaySettleDetailByApplyNo(@RequestBody CalSettleCondition condition) {

        //申请编号
        String applyNo = condition.getApplyNo();

        SettleStayVo vo = new SettleStayVo();

        //根据申请编号查询合同主表
        BasicMainInfo basicMainInfo = basicMainInfoService.getOne(Wrappers.<BasicMainInfo>query().lambda()
                        .eq(BasicMainInfo::getApplyNo, applyNo)
                , false
        );

        if (basicMainInfo != null) {
            //根据申请编号查询已还期数
            SettleStayVo voQuery = basicMainInfoMapper.getStaySettleDetail(basicMainInfo.getContractNo());
            if (voQuery != null && voQuery.getAlreadyPeriods() != null) {
                vo.setAlreadyPeriods(voQuery.getAlreadyPeriods());
            } else {
                vo.setAlreadyPeriods(0);//默认还款期数为0
            }

            //根据合同编号查询合同渠道信息记录表
            BasicChannelInfo basicChannelInfo = basicChannelInfoService.getOne(Wrappers.<BasicChannelInfo>query().lambda()
                            .eq(BasicChannelInfo::getContractNo, basicMainInfo.getContractNo())
                    , false
            );
            if (basicChannelInfo != null) {
                vo.setChannelFullName(basicChannelInfo.getChannelFullName());//合作商全称
            }

            //根据合同编号查询合同金融协议表
            BasicFinancialAgreement basicFinancialAgreement = basicFinancialAgreementService.getOne(Wrappers.<BasicFinancialAgreement>query().lambda()
                            .eq(BasicFinancialAgreement::getContractNo, basicMainInfo.getContractNo())
                    , false
            );
            if (basicFinancialAgreement != null) {
                vo.setSettleRate(basicFinancialAgreement.getSettleRate());//结算利率
                vo.setLoanTerm(basicFinancialAgreement.getLoanTerm());//融资期数
            }

            //组装数据
            vo.setApplyNo(applyNo);//申请编号
            vo.setContractNo(basicMainInfo.getContractNo());//合同编号
            vo.setBusinessType(basicMainInfo.getBusinessType());//业务类型
            vo.setContractStatus(basicMainInfo.getContractStatus());//合同状态
            vo.setStartDate(basicMainInfo.getStartDate());//合同激活时间
            vo.setEndDate(basicMainInfo.getEndDate());//合同到期日期
            vo.setProductName(basicMainInfo.getProductName());//产品名称
            vo.setNoAlreadyPeriods(vo.getLoanTerm() - vo.getAlreadyPeriods());//未还期数=总期数-已还期数

            //查询合同与客户关系表
            BasicContractCustRelation basicContractCustRelation = basicContractCustRelationService.getOne(Wrappers.<BasicContractCustRelation>lambdaQuery().
                    eq(BasicContractCustRelation::getContractNo, basicMainInfo.getContractNo())
                    .eq(BasicContractCustRelation::getCustRole, PersonRoleTypeEnum.MAIN_PERSON)
            );
            //查询主借人信息
            BasicCustBaseInfo basicCustBaseInfo = basicCustBaseInfoService.getOne(Wrappers.<BasicCustBaseInfo>query().lambda()
                    .eq(BasicCustBaseInfo::getCustNo, basicContractCustRelation.getCustNo())
            );
            vo.setCustName(basicCustBaseInfo.getCustName());//客户姓名
        }

        return IResponse.success(vo);
    }

    @PostMapping(value = "/getBatchDate")
    @ApiOperation(value = "获取日结日期")
    public IResponse getBatchDate(@RequestParam(value = "contractNo") String contractNo) {
        AfsBatchInfo afsBatchInfo = afsBatchInfoService.getSystemBatchInfo("icos");
        //还款计划表
        List<BasicRepaymentPlan> listUnpaidTop = basicRepaymentPlanService.list(Wrappers.<BasicRepaymentPlan>query().lambda()
                .eq(BasicRepaymentPlan::getContractNo, contractNo)//合同编号
                .ge(BasicRepaymentPlan::getDueDate, afsBatchInfo.getBatchDate())
                .orderByAsc(BasicRepaymentPlan::getTermNo)//期数排序
        );
        if (EmptyUtils.isNotEmpty(listUnpaidTop)) {
            BasicRepaymentPlan basicRepaymentPlan = listUnpaidTop.get(0);
            afsBatchInfo.setLastBatchDate(DateUtil.format(basicRepaymentPlan.getDueDate(), "yyyyMMdd"));
        }
        return IResponse.success(afsBatchInfo);
    }

    @PostMapping(value = "/getPrepaymentRate")
    @ApiOperation(value = "获取提前终止费率")
    public IResponse getPrepaymentRate(@RequestBody CalSettleCondition condition) {
        //合同号
        String contractNo = condition.getContractNo();
        //根据合同号查询合同信息，是否存在
        BasicMainInfo basicMainInfo = basicMainInfoService.getOne(Wrappers.<BasicMainInfo>query().lambda()
                        .eq(BasicMainInfo::getContractNo, contractNo)
                , false
        );
        BasicProductParam basicProductParam = basicProductParamService.getOne(Wrappers.<BasicProductParam>query().lambda()
                        .eq(BasicProductParam::getContractNo, contractNo)//合同编号
                        .eq(BasicProductParam::getProductId, basicMainInfo.getProductId())//产品ID
                        .eq(BasicProductParam::getAtomKey, ProductAtomEnum.SETTLE_COST)//费用比率
                , false
        );
        //提前终止费率
        BigDecimal prepaymentRate = BigDecimal.ZERO;
        if (basicProductParam != null) {
            prepaymentRate = new BigDecimal(basicProductParam.getAtomValue());
            prepaymentRate = prepaymentRate.compareTo(BigDecimal.ZERO) == 0 ? prepaymentRate : prepaymentRate.divide(new BigDecimal("100"), 2, BigDecimal.ROUND_HALF_UP);
        }
        return IResponse.success(prepaymentRate);
    }

    @PostMapping(value = "/calSettleResult")
    @ApiOperation(value = "计算试算结果")
    public IResponse<SettleResultVo> calSettleResult(@RequestBody CalSettleCondition condition) {
        if (EmptyUtils.isEmpty(condition.getContractNo())) {
            return IResponse.fail("合同号码不能为空");
        }
        if (EmptyUtils.isEmpty(condition.getExecuteTime())) {
            return IResponse.fail("计算日期不能为空");
        }
        if (EmptyUtils.isEmpty(condition.getCalculateTime())) {
            //请求日期为空时，插入当天时间
            condition.setCalculateTime(DateUtil.date());
        }
        //合同号
        String contractNo = condition.getContractNo();
        //计算日期
        Date executeTime = condition.getExecuteTime();
        //请求日期
        Date calculateTime = condition.getCalculateTime();
        //豁免单费用
        BigDecimal exemptBillCostValue = condition.getExemptBillCost();
        //还款方式
        String repayMode = condition.getRepayMode();

        //根据合同号查询合同信息，是否存在
        BasicMainInfo basicMainInfo = basicMainInfoService.getOne(Wrappers.<BasicMainInfo>query().lambda()
                        .eq(BasicMainInfo::getContractNo, contractNo)
                , false
        );
        if (EmptyUtils.isEmpty(basicMainInfo)) {
            return IResponse.fail("没有此合同信息");
        }

        //还款计划表-已还【真正已经还款的期数】
        List<BasicRepaymentPlan> listRepaid = basicRepaymentPlanService.list(Wrappers.<BasicRepaymentPlan>query().lambda()
                .eq(BasicRepaymentPlan::getContractNo, contractNo)//合同编号
                .eq(BasicRepaymentPlan::getStatus, RepaymentStatusEnum.REPAID)//状态
                .orderByAsc(BasicRepaymentPlan::getTermNo)//期数排序
        );

        //还款计划表【上一期】
        List<BasicRepaymentPlan> listUnpaidTop = basicRepaymentPlanService.list(Wrappers.<BasicRepaymentPlan>query().lambda()
                .eq(BasicRepaymentPlan::getContractNo, contractNo)//合同编号
                .lt(BasicRepaymentPlan::getDueDate, executeTime)//应还款日期小于计算日期
                .orderByDesc(BasicRepaymentPlan::getTermNo)//期数排序
        );

        //还款计划表-未偿【计算日期之后未还的都算未偿】【未偿存在当期，如果不存在，证明全部逾期】
        List<BasicRepaymentPlan> listUnpaid = basicRepaymentPlanService.list(Wrappers.<BasicRepaymentPlan>query().lambda()
                .eq(BasicRepaymentPlan::getContractNo, contractNo)//合同编号
                .ge(BasicRepaymentPlan::getDueDate, executeTime)//应还款日期大于等于计算日期
                .eq(BasicRepaymentPlan::getStatus, RepaymentStatusEnum.UNPAID)//状态等于未还
                .orderByAsc(BasicRepaymentPlan::getTermNo)//期数排序
        );

        //还款计划表-逾期【计算日期之前未还的都算逾期】
        List<BasicRepaymentPlan> listOverdue = basicRepaymentPlanService.list(Wrappers.<BasicRepaymentPlan>query().lambda()
                .eq(BasicRepaymentPlan::getContractNo, contractNo)//合同编号
                .lt(BasicRepaymentPlan::getDueDate, executeTime)//应还款日期小于计算日期
                .ne(BasicRepaymentPlan::getStatus, RepaymentStatusEnum.REPAID)//状态不等于已还
                .orderByDesc(BasicRepaymentPlan::getTermNo)//期数排序
        );

        //还款计划表-待逾期【请求日之后的还款期数的应还款日到计算日期】
        List<BasicRepaymentPlan> listOverdueWait = basicRepaymentPlanService.list(Wrappers.<BasicRepaymentPlan>query().lambda()
                .eq(BasicRepaymentPlan::getContractNo, contractNo)//合同编号
                .le(BasicRepaymentPlan::getDueDate, executeTime)//应还款日期小于等于计算日期
                .gt(BasicRepaymentPlan::getDueDate, calculateTime)//应还款日期大于请求日期
                .eq(BasicRepaymentPlan::getStatus, RepaymentStatusEnum.UNPAID)//状态等于未还
                .orderByDesc(BasicRepaymentPlan::getTermNo)//期数排序
        );
        //还款计划表-已经逾期
        List<BasicRepaymentPlan> listOverdueAlready = basicRepaymentPlanService.list(Wrappers.<BasicRepaymentPlan>query().lambda()
                .eq(BasicRepaymentPlan::getContractNo, contractNo)//合同编号
                .eq(BasicRepaymentPlan::getStatus, RepaymentStatusEnum.OVERDUE)//状态等于逾期
                .orderByDesc(BasicRepaymentPlan::getTermNo)//期数排序
        );

        //合同每期罚息明细
        List<BasicPenaltyInterest> basicPenaltyInterestList = basicPenaltyInterestService.list(Wrappers.<BasicPenaltyInterest>query().lambda()
                .eq(BasicPenaltyInterest::getContractNo, contractNo)//合同编号
                .orderByDesc(BasicPenaltyInterest::getTermNo)//期数排序
        );

        //杂费，指的是客户的费用，可以从basic_expense_record表里面取费用信息（记得剔除罚息）
        List<BasicExpenseRecord> basicExpenseRecordList = basicExpenseRecordService.list(Wrappers.<BasicExpenseRecord>query().lambda()
                .eq(BasicExpenseRecord::getContractNo, contractNo)//合同编号
                .eq(BasicExpenseRecord::getStatus, ExpenseStatusEnum.unsettle)
                .ne(BasicExpenseRecord::getCostType, FeeTypeEnum.penalty)
        );
        //未分配金额【预收款的值】查询收据表
        List<BasicReceiptRecord> basicReceiptRecords = basicReceiptRecordService.list(Wrappers.<BasicReceiptRecord>query().lambda()
                .ne(BasicReceiptRecord::getReceiptStatus, ReceiptStatusEnum.revoke)
                .eq(BasicReceiptRecord::getContractNo, contractNo)
                .gt(BasicReceiptRecord::getUnusedAmt, BigDecimal.ZERO)
        );

        //合同金融协议表,为了拿到逾期利率
        BasicFinancialAgreement basicFinancialAgreement = basicFinancialAgreementService.getOne(Wrappers.<BasicFinancialAgreement>lambdaQuery()
                .eq(BasicFinancialAgreement::getContractNo, contractNo)
                .eq(BasicFinancialAgreement::getCostType, AssetTypeEnum.CAR_AMT)
        );

        BigDecimal unpayedCaptial = BigDecimal.ZERO;//未偿本金
        BigDecimal overdueAmount = BigDecimal.ZERO;//逾期租金【结清日期以上的未还的都算逾期租金】
        BigDecimal interestReceivable = BigDecimal.ZERO;//利息应收
        BigDecimal unpayedOverdueInterest = BigDecimal.ZERO;//未付逾期利息【请求日期之前的罚息金额】
        BigDecimal prepaymentCharge = BigDecimal.ZERO;//提前终止费用
        BigDecimal overdueInterestReceivable = BigDecimal.ZERO;//应计逾期利息【1、逾期还款期数的继续算罚息，2、请求日之后的还款期数的应还款日到计算日期】
        BigDecimal prepaymentCost = BigDecimal.ZERO;//提前终止金额
        BigDecimal otherCost = BigDecimal.ZERO;//杂费
        BigDecimal unusedDeposit = BigDecimal.ZERO;//未分配金额【预收款的值】
        BigDecimal exemptBillCost = BigDecimal.ZERO;//豁免单费用
        BigDecimal exemptBillCostMin = BigDecimal.ZERO;//最小豁免单费用
        BigDecimal exemptBillCostMax = BigDecimal.ZERO;//最大豁免单费用
        BigDecimal exemptAmount = BigDecimal.ZERO;//豁免费用
        BigDecimal exemptOverdueInterest = BigDecimal.ZERO;//豁免罚息
        BigDecimal receivableAmount = BigDecimal.ZERO;//应收金额

        for (BasicRepaymentPlan basicRepaymentPlan : listUnpaid) {
            //未偿本金
            unpayedCaptial = basicRepaymentPlan.getReceivablePrinciple().add(unpayedCaptial);
        }

        for (BasicRepaymentPlan basicRepaymentPlan : listOverdue) {
            //逾期租金
            overdueAmount = basicRepaymentPlan.getReceivableRent().add(overdueAmount);
        }

        //应计逾期利息
        for (BasicRepaymentPlan basicRepaymentPlan : listOverdueAlready) {
            //应计逾期利息第一种情况====>请求日到计算日【不包含】生成的的罚息=租金*利率*天数/100
            overdueInterestReceivable = overdueInterestReceivable
                    .add(basicRepaymentPlan.getReceivableRent()
                            .multiply(basicFinancialAgreement.getOverDueRate())
                            .multiply(BigDecimal.valueOf(DateUtil.between(executeTime, calculateTime, DateUnit.DAY)))
                            .divide(new BigDecimal("36000"), 2, BigDecimal.ROUND_HALF_UP)
                    );
        }
        for (BasicRepaymentPlan basicRepaymentPlan : listOverdueWait) {
            //应计逾期利息第二种情况====>请求日之后的还款期数的应还款日到计算日期=租金*利率*天数/100
            overdueInterestReceivable = overdueInterestReceivable
                    .add(basicRepaymentPlan.getReceivableRent()
                            .multiply(basicFinancialAgreement.getOverDueRate())
                            .multiply(BigDecimal.valueOf(DateUtil.between(executeTime, basicRepaymentPlan.getDueDate(), DateUnit.DAY)))
                            .divide(new BigDecimal("36000"), 2, BigDecimal.ROUND_HALF_UP)
                    );
        }

        for (BasicPenaltyInterest basicPenaltyInterest : basicPenaltyInterestList) {
            //未付逾期利息
            unpayedOverdueInterest = basicPenaltyInterest.getTotalPenalty().subtract(basicPenaltyInterest.getReceivedAmt()).subtract(basicPenaltyInterest.getRealExemptionAmt()).add(unpayedOverdueInterest);
        }

        for (BasicExpenseRecord basicExpenseRecord : basicExpenseRecordList) {
            //杂费
            otherCost = basicExpenseRecord.getRemainingAmt().add(otherCost);
            //预计豁免费用
            exemptAmount = basicExpenseRecord.getRemainingAmt().add(exemptAmount);
        }

        for (BasicReceiptRecord basicReceiptRecord : basicReceiptRecords) {
            //未分配金额
            unusedDeposit = basicReceiptRecord.getUnusedAmt().add(unusedDeposit);
        }

        if (EmptyUtils.isNotEmpty(listUnpaid) && EmptyUtils.isNotEmpty(listUnpaidTop)) {
            //还款计划表-未偿当期
            BasicRepaymentPlan oneUnpaid = listUnpaid.get(0);
            //还款计划表-逾期当期
            BasicRepaymentPlan oneOverdue = listUnpaidTop.get(0);
            //利息应收 = 未偿当期的应收利息[日结时间拿到当期]/(上期和当期的实际天数)*（计算日期-上期应还日期-1天）
            interestReceivable = oneUnpaid.getReceivableInterest()
                    .divide(BigDecimal.valueOf(DateUtil.between(oneOverdue.getDueDate(), oneUnpaid.getDueDate(), DateUnit.DAY)), 2, BigDecimal.ROUND_HALF_UP)
                    .multiply(BigDecimal.valueOf(DateUtil.between(executeTime, oneOverdue.getDueDate(), DateUnit.DAY)));
        } else if (EmptyUtils.isEmpty(listUnpaidTop)) {
            //还款计划表-未偿当期
            BasicRepaymentPlan oneUnpaid = listUnpaid.get(0);
            //利息应收 = 未偿当期的应收利息[日结时间拿到当期]/(上期和当期的实际天数)*（计算日期-上期应还日期-1天）
            interestReceivable = oneUnpaid.getReceivableInterest()
                    .divide(BigDecimal.valueOf(DateUtil.between(basicMainInfo.getStartDate(), oneUnpaid.getDueDate(), DateUnit.DAY)), 2, BigDecimal.ROUND_HALF_UP)
                    .multiply(BigDecimal.valueOf(DateUtil.between(basicMainInfo.getStartDate(), executeTime, DateUnit.DAY)));
        }

        BasicProductParam basicProductParam = basicProductParamService.getOne(Wrappers.<BasicProductParam>query().lambda()
                        .eq(BasicProductParam::getContractNo, contractNo)//合同编号
                        .eq(BasicProductParam::getProductId, basicMainInfo.getProductId())//产品ID
                        .eq(BasicProductParam::getAtomKey, ProductAtomEnum.SETTLE_COST)//费用比率
                , false
        );
        BigDecimal prepaymentRate = BigDecimal.ZERO;//提前终止费用比率
        if (basicProductParam != null) {
            prepaymentRate = new BigDecimal(basicProductParam.getAtomValue());
            prepaymentRate = prepaymentRate.compareTo(BigDecimal.ZERO) == 0 ? prepaymentRate : prepaymentRate.divide(new BigDecimal("100"), 2, BigDecimal.ROUND_HALF_UP);
        }
        //提前终止费用
        prepaymentCharge = unpayedCaptial.multiply(prepaymentRate);//暂定利率从产品获取
        //提前终止金额
        prepaymentCost = unpayedCaptial.add(overdueAmount).add(interestReceivable).add(prepaymentCharge);

        //豁免单费用
        ImmunityDto dto = new ImmunityDto();
        dto.setContractNo(contractNo);
        IResponse iResponse = immunityFeign.queryManageCostExemptBill(dto);
        if (iResponse != null && "0000".equals(iResponse.getCode()) && iResponse.getData() != null) {
            exemptBillCostMin = new BigDecimal(JSON.parseObject(JSON.toJSONString(iResponse.getData())).get("minAmt").toString());
            exemptBillCostMax = new BigDecimal(JSON.parseObject(JSON.toJSONString(iResponse.getData())).get("maxAmt").toString());
            if (exemptBillCostMax.compareTo(exemptAmount.add(unpayedOverdueInterest)) == 1) {
                exemptBillCostMax = exemptAmount.add(unpayedOverdueInterest);
            }
            exemptBillCost = exemptBillCostMin;//豁免单费用=默认最小豁免单费用
        }
        //根据前端传输的豁免单费用计算，金额大于0才能参与
        if (exemptBillCostValue != null || exemptBillCostValue.compareTo(BigDecimal.ZERO) == 1) {
            exemptBillCost = exemptBillCostValue;//豁免单费用
        }
        //计算出最终的豁免费用以及豁免罚息
        if (exemptAmount.compareTo(exemptBillCost) == 1) {
            exemptAmount = exemptBillCost;//最高只能拿到所有的豁免
        } else {
            exemptOverdueInterest = exemptBillCost.subtract(exemptAmount);//计算出豁免罚息金额
        }

        //应收金额【提前终止金额+未付逾期利息+应付逾期利息+杂费-未分配金额—豁免费用-豁免罚息】
        receivableAmount = prepaymentCost
                .add(unpayedOverdueInterest)
                .add(overdueInterestReceivable)
                .add(otherCost)
                .subtract(unusedDeposit)
                .subtract(exemptAmount)
                .subtract(exemptOverdueInterest);

        //返回的对象
        SettleResultVo vo = new SettleResultVo();
        vo.setContractNo(basicMainInfo.getContractNo());//合同号码
        vo.setCalDate(calculateTime);//提前还款日期
        vo.setContractStatus(basicMainInfo.getContractStatus());//合同状态
        vo.setRepaymentMethod(repayMode);//还款方式
        vo.setPaymentPeroid(listRepaid.size());//已还期数
        vo.setUnpayedCaptial(unpayedCaptial.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : unpayedCaptial.setScale(2, BigDecimal.ROUND_HALF_UP));//未偿本金
        vo.setOverdueAmount(overdueAmount.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : overdueAmount.setScale(2, BigDecimal.ROUND_HALF_UP));//逾期租金
        vo.setInterestReceivable(interestReceivable.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : interestReceivable.setScale(2, BigDecimal.ROUND_HALF_UP));//利息应收
        vo.setUnpayedOverdueInterest(unpayedOverdueInterest.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : unpayedOverdueInterest.setScale(2, BigDecimal.ROUND_HALF_UP));//未付逾期利息
        vo.setPrepaymentCharge(prepaymentCharge.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : prepaymentCharge.setScale(2, BigDecimal.ROUND_HALF_UP));//提前终止费用
        vo.setOverdueInterestReceivable(overdueInterestReceivable.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : overdueInterestReceivable.setScale(2, BigDecimal.ROUND_HALF_UP));//应计逾期利息
        vo.setPrepaymentCost(prepaymentCost.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : prepaymentCost.setScale(2, BigDecimal.ROUND_HALF_UP));//提前终止金额
        vo.setOtherCost(otherCost.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : otherCost.setScale(2, BigDecimal.ROUND_HALF_UP));//杂费
        vo.setUnusedDeposit(unusedDeposit.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : unusedDeposit.setScale(2, BigDecimal.ROUND_HALF_UP));//未分配金额
        vo.setExemptBillCost(exemptBillCost.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : exemptBillCost.setScale(2, BigDecimal.ROUND_HALF_UP));//豁免单费用=默认最小豁免单费用
        vo.setExemptBillCostMin(exemptBillCostMin);//最小豁免单费用
        vo.setExemptBillCostMax(exemptBillCostMax);//最打豁免单费用
        vo.setExemptAmount(exemptAmount.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : exemptAmount.setScale(2, BigDecimal.ROUND_HALF_UP));//豁免费用
        vo.setExemptOverdueInterest(exemptOverdueInterest);//豁免罚息
        vo.setReceivableAmount(receivableAmount.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : receivableAmount.setScale(2, BigDecimal.ROUND_HALF_UP));//应收金额
        return IResponse.success(vo);
    }

    @PostMapping(value = "/queryUnpayedOverdueInterestDetail")
    @ApiOperation(value = "未付逾期利息查询")
    public IResponse queryUnpayedOverdueInterestDetail(@RequestBody QueryCondition<CalSettleCondition> condition) {
        //合同每期罚息明细
        IPage<List<BasicPenaltyInterest>> list = basicPenaltyInterestService.page(new Page(condition.getPageNumber(), condition.getPageSize()), Wrappers.<BasicPenaltyInterest>query().lambda()
                .eq(BasicPenaltyInterest::getContractNo, condition.getCondition().getContractNo())//合同编号
                .orderByAsc(BasicPenaltyInterest::getTermNo)//期数排序
        );
        return IResponse.success(list);
    }

    @PostMapping(value = "/queryOtherCostDetail")
    @ApiOperation(value = "查询杂费详情")
    public IResponse queryOtherCostDetail(@RequestBody QueryCondition<CalSettleCondition> condition) {
        //杂费，指的是客户的费用，可以从basic_expense_record表里面取费用信息（记得剔除罚息）
        IPage<List<BasicExpenseRecord>> list = basicExpenseRecordService.page(new Page(condition.getPageNumber(), condition.getPageSize()), Wrappers.<BasicExpenseRecord>query().lambda()
                .eq(BasicExpenseRecord::getContractNo, condition.getCondition().getContractNo())//合同编号
                .eq(BasicExpenseRecord::getStatus, ExpenseStatusEnum.unsettle)
                .ne(BasicExpenseRecord::getCostType, FeeTypeEnum.penalty)
        );
        return IResponse.success(list);
    }

    @PostMapping(value = "/calSettleResultToCms")
    @ApiOperation(value = "计算试算结果供（CMS接口聚合使用）")
    public IResponse<List<SettleResultVo>> calSettleResultToCms(@RequestBody CalSettleCondition condition) {
        IResponse<SettleResultVo> settleResultVoIResponse = this.calSettleResult(condition);
        if (CommonConstants.SUCCESS.equals(settleResultVoIResponse.getCode())) {
            SettleResultVo data = settleResultVoIResponse.getData();
            List list = new ArrayList();
            list.add(data);
            return IResponse.success(list);
        } else {
            return IResponse.fail("试算失败！");
        }
    }

    @ApiOperation(value = "插入提前终止费用")
    @PostMapping("/setPrepaymentCharge")
    @Transactional(rollbackFor = Exception.class)
    public IResponse<Boolean> setPrepaymentCharge(@RequestBody StaySettleVo vo) {
        BasicExpenseRecord basicExpenseRecord = new BasicExpenseRecord();
        basicExpenseRecord.setContractNo(vo.getContractNo());
        basicExpenseRecord.setCostAmt(vo.getCostAmt());
        basicExpenseRecord.setRemainingAmt(vo.getCostAmt());
        basicExpenseRecord.setEndDate(vo.getEndDate());
        basicExpenseRecord.setStatus(ExpenseStatusEnum.unsettle);
        basicExpenseRecord.setCostType(FeeTypeEnum.prepaymentCharge);
        BasicExpenseRecordDetail expenseRecordDetail = new BasicExpenseRecordDetail();
        BeanUtils.copyProperties(basicExpenseRecord, expenseRecordDetail);
        basicExpenseRecordDetailService.save(expenseRecordDetail);
        basicExpenseRecordService.save(basicExpenseRecord);
        return IResponse.success("插入提前终止费用成功");
    }

    @ApiOperation(value = "删除提前终止费用")
    @PostMapping("/delPrepaymentCharge")
    @Transactional(rollbackFor = Exception.class)
    public IResponse<Boolean> delPrepaymentCharge(@RequestBody StaySettleVo vo) {
        basicExpenseRecordDetailService.remove(Wrappers.<BasicExpenseRecordDetail>lambdaQuery()
                .eq(BasicExpenseRecordDetail::getContractNo, vo.getContractNo())
                .eq(BasicExpenseRecordDetail::getCostType, FeeTypeEnum.prepaymentCharge));
        basicExpenseRecordService.remove(Wrappers.<BasicExpenseRecord>lambdaQuery()
                .eq(BasicExpenseRecord::getContractNo, vo.getContractNo())
                .eq(BasicExpenseRecord::getCostType, FeeTypeEnum.prepaymentCharge));
        return IResponse.success("删除提前终止费用成功");
    }

    @ApiOperation(value = "豁免单费用冲抵")
    @PostMapping("/setExemptBillMitigate")
    @Transactional(rollbackFor = Exception.class)
    public IResponse<Boolean> setExemptBillMitigate(@RequestBody StaySettleVo vo) {
        BigDecimal exemptBillCost = BigDecimal.ZERO;
        BigDecimal exemptBill = BigDecimal.ZERO;
        if (vo.getExemptBillCost().compareTo(BigDecimal.ZERO) > 0) {
            BasicExpenseRecord expenseRecord = basicExpenseRecordService.getOne(Wrappers.<BasicExpenseRecord>lambdaQuery()
                    .eq(BasicExpenseRecord::getContractNo, vo.getContractNo())
                    .eq(BasicExpenseRecord::getCostType, FeeTypeEnum.prepaymentCharge));
            BasicExpenseRecordDetail expenseRecordDetail = basicExpenseRecordDetailService.getOne(Wrappers.<BasicExpenseRecordDetail>lambdaQuery()
                    .eq(BasicExpenseRecordDetail::getContractNo, vo.getContractNo())
                    .eq(BasicExpenseRecordDetail::getCostType, FeeTypeEnum.prepaymentCharge));
            if (vo.getExemptBillCost().compareTo(expenseRecord.getRemainingAmt()) >= 0) {
                exemptBillCost = vo.getExemptBillCost().subtract(expenseRecord.getRemainingAmt());
                //合同费用记录表冲抵
                expenseRecord.setExemptBillMitigate(expenseRecord.getRemainingAmt());
                expenseRecord.setExemptedAmt(expenseRecord.getExemptedAmt().add(expenseRecord.getRemainingAmt()));
                expenseRecord.setExemptionAmt(expenseRecord.getExemptionAmt().add(expenseRecord.getRemainingAmt()));
                expenseRecord.setRemainingAmt(BigDecimal.ZERO);
                expenseRecord.setStatus(ExpenseStatusEnum.settle);
                basicExpenseRecordService.updateById(expenseRecord);
                //合同费用记录明细表冲抵
                expenseRecordDetail.setExemptBillMitigate(expenseRecordDetail.getRemainingAmt());
                expenseRecordDetail.setExemptedAmt(expenseRecordDetail.getExemptedAmt().add(expenseRecordDetail.getRemainingAmt()));
                expenseRecordDetail.setExemptionAmt(expenseRecordDetail.getExemptionAmt().add(expenseRecordDetail.getRemainingAmt()));
                expenseRecordDetail.setRemainingAmt(BigDecimal.ZERO);
                expenseRecordDetail.setStatus(ExpenseStatusEnum.settle);
                basicExpenseRecordDetailService.updateById(expenseRecordDetail);
            } else {
                //合同费用记录表冲抵
                expenseRecord.setExemptBillMitigate(vo.getExemptBillCost());
                expenseRecord.setExemptedAmt(expenseRecord.getExemptedAmt().add(vo.getExemptBillCost()));
                expenseRecord.setExemptionAmt(expenseRecord.getExemptionAmt().add(vo.getExemptBillCost()));
                expenseRecord.setRemainingAmt(expenseRecord.getRemainingAmt().subtract(vo.getExemptBillCost()));
                basicExpenseRecordService.updateById(expenseRecord);
                //合同费用记录明细表冲抵
                expenseRecordDetail.setExemptBillMitigate(vo.getExemptBillCost());
                expenseRecordDetail.setExemptedAmt(expenseRecordDetail.getExemptedAmt().add(expenseRecordDetail.getRemainingAmt()));
                expenseRecordDetail.setExemptionAmt(expenseRecordDetail.getExemptionAmt().add(expenseRecordDetail.getRemainingAmt()));
                expenseRecordDetail.setRemainingAmt(expenseRecordDetail.getRemainingAmt().subtract(vo.getExemptBillCost()));
                basicExpenseRecordDetailService.updateById(expenseRecordDetail);
                exemptBillCost = BigDecimal.ZERO;
            }
        }
        if (exemptBillCost.compareTo(BigDecimal.ZERO) > 0) {
            BigDecimal exemptBillCostDetail = exemptBillCost;
            List<BasicExpenseRecord> expenseRecordList = basicExpenseRecordService.list(Wrappers.<BasicExpenseRecord>lambdaQuery()
                    .eq(BasicExpenseRecord::getContractNo, vo.getContractNo())
                    .ne(BasicExpenseRecord::getCostType, FeeTypeEnum.prepaymentCharge)
                    .ne(BasicExpenseRecord::getCostType, FeeTypeEnum.penalty)
                    .orderByAsc(BasicExpenseRecord::getCostType));
            List<BasicExpenseRecordDetail> expenseRecordDetailList = basicExpenseRecordDetailService.list(Wrappers.<BasicExpenseRecordDetail>lambdaQuery()
                    .eq(BasicExpenseRecordDetail::getContractNo, vo.getContractNo())
                    .ne(BasicExpenseRecordDetail::getCostType, FeeTypeEnum.prepaymentCharge)
                    .ne(BasicExpenseRecordDetail::getCostType, FeeTypeEnum.penalty)
                    .orderByAsc(BasicExpenseRecordDetail::getCostType));
            for (BasicExpenseRecord expenseRecord : expenseRecordList) {
                if (exemptBillCost.compareTo(expenseRecord.getRemainingAmt()) >= 0) {
                    exemptBillCost = exemptBillCost.subtract(expenseRecord.getRemainingAmt());
                    exemptBill = exemptBillCost;
                    //合同费用记录表冲抵
                    expenseRecord.setExemptBillMitigate(expenseRecord.getRemainingAmt());
                    expenseRecord.setExemptedAmt(expenseRecord.getExemptedAmt().add(expenseRecord.getRemainingAmt()));
                    expenseRecord.setExemptionAmt(expenseRecord.getExemptionAmt().add(expenseRecord.getRemainingAmt()));
                    expenseRecord.setRemainingAmt(BigDecimal.ZERO);
                    expenseRecord.setStatus(ExpenseStatusEnum.settle);
                    basicExpenseRecordService.updateById(expenseRecord);
                } else {
                    //合同费用记录表冲抵
                    expenseRecord.setExemptBillMitigate(exemptBillCost);
                    expenseRecord.setExemptedAmt(expenseRecord.getExemptedAmt().add(exemptBillCost));
                    expenseRecord.setExemptionAmt(expenseRecord.getExemptionAmt().add(exemptBillCost));
                    expenseRecord.setRemainingAmt(expenseRecord.getRemainingAmt().subtract(exemptBillCost));
                    basicExpenseRecordService.updateById(expenseRecord);
                    exemptBill = BigDecimal.ZERO;
                    break;
                }
            }
            for (BasicExpenseRecordDetail expenseRecordDetail : expenseRecordDetailList) {
                if (exemptBillCostDetail.compareTo(expenseRecordDetail.getRemainingAmt()) >= 0) {
                    exemptBillCostDetail = exemptBillCostDetail.subtract(expenseRecordDetail.getRemainingAmt());
                    //合同费用记录明细表冲抵
                    expenseRecordDetail.setExemptBillMitigate(expenseRecordDetail.getRemainingAmt());
                    expenseRecordDetail.setExemptedAmt(expenseRecordDetail.getExemptedAmt().add(expenseRecordDetail.getRemainingAmt()));
                    expenseRecordDetail.setExemptionAmt(expenseRecordDetail.getExemptionAmt().add(expenseRecordDetail.getRemainingAmt()));
                    expenseRecordDetail.setRemainingAmt(BigDecimal.ZERO);
                    expenseRecordDetail.setStatus(ExpenseStatusEnum.settle);
                    basicExpenseRecordDetailService.updateById(expenseRecordDetail);
                } else {
                    //合同费用记录明细表冲抵
                    expenseRecordDetail.setExemptBillMitigate(exemptBillCostDetail);
                    expenseRecordDetail.setExemptedAmt(expenseRecordDetail.getExemptedAmt().add(exemptBillCostDetail));
                    expenseRecordDetail.setExemptionAmt(expenseRecordDetail.getExemptionAmt().add(exemptBillCostDetail));
                    expenseRecordDetail.setRemainingAmt(expenseRecordDetail.getRemainingAmt().subtract(exemptBillCostDetail));
                    basicExpenseRecordDetailService.updateById(expenseRecordDetail);
                    break;
                }
            }
        }
        if (exemptBill.compareTo(BigDecimal.ZERO) > 0) {
            BigDecimal exemptBillCostDetail = exemptBill;
            BigDecimal exemptBillCostInterest = exemptBill;
            List<BasicExpenseRecord> expenseRecordList = basicExpenseRecordService.list(Wrappers.<BasicExpenseRecord>lambdaQuery()
                    .eq(BasicExpenseRecord::getContractNo, vo.getContractNo())
                    .eq(BasicExpenseRecord::getCostType, FeeTypeEnum.penalty));
            List<BasicExpenseRecordDetail> expenseRecordDetailList = basicExpenseRecordDetailService.list(Wrappers.<BasicExpenseRecordDetail>lambdaQuery()
                    .eq(BasicExpenseRecordDetail::getContractNo, vo.getContractNo())
                    .eq(BasicExpenseRecordDetail::getCostType, FeeTypeEnum.penalty));
            List<BasicPenaltyInterest> penaltyInterestList = basicPenaltyInterestService.list(Wrappers.<BasicPenaltyInterest>lambdaQuery()
                    .eq(BasicPenaltyInterest::getContractNo, vo.getContractNo()).orderByAsc(BasicPenaltyInterest::getTermNo));
            for (BasicExpenseRecord expenseRecord : expenseRecordList) {
                if (exemptBill.compareTo(expenseRecord.getRemainingAmt()) >= 0) {
                    exemptBill = exemptBill.subtract(expenseRecord.getRemainingAmt());
                    //合同费用记录表冲抵
                    expenseRecord.setExemptBillMitigate(expenseRecord.getRemainingAmt());
                    expenseRecord.setExemptedAmt(expenseRecord.getExemptedAmt().add(expenseRecord.getRemainingAmt()));
                    expenseRecord.setExemptionAmt(expenseRecord.getExemptionAmt().add(expenseRecord.getRemainingAmt()));
                    expenseRecord.setRemainingAmt(BigDecimal.ZERO);
                    expenseRecord.setStatus(ExpenseStatusEnum.settle);
                    basicExpenseRecordService.updateById(expenseRecord);
                } else {
                    //合同费用记录表冲抵
                    expenseRecord.setExemptBillMitigate(exemptBill);
                    expenseRecord.setExemptedAmt(expenseRecord.getExemptedAmt().add(exemptBill));
                    expenseRecord.setExemptionAmt(expenseRecord.getExemptionAmt().add(exemptBill));
                    expenseRecord.setRemainingAmt(expenseRecord.getRemainingAmt().subtract(exemptBill));
                    basicExpenseRecordService.updateById(expenseRecord);
                    break;
                }
            }
            for (BasicExpenseRecordDetail expenseRecordDetail : expenseRecordDetailList) {
                if (exemptBillCostDetail.compareTo(expenseRecordDetail.getRemainingAmt()) >= 0) {
                    exemptBillCostDetail = exemptBillCostDetail.subtract(expenseRecordDetail.getRemainingAmt());
                    //合同费用记录明细表冲抵
                    expenseRecordDetail.setExemptBillMitigate(expenseRecordDetail.getRemainingAmt());
                    expenseRecordDetail.setExemptedAmt(expenseRecordDetail.getExemptedAmt().add(expenseRecordDetail.getRemainingAmt()));
                    expenseRecordDetail.setExemptionAmt(expenseRecordDetail.getExemptionAmt().add(expenseRecordDetail.getRemainingAmt()));
                    expenseRecordDetail.setRemainingAmt(BigDecimal.ZERO);
                    expenseRecordDetail.setStatus(ExpenseStatusEnum.settle);
                    basicExpenseRecordDetailService.updateById(expenseRecordDetail);
                } else {
                    //合同费用记录明细表冲抵
                    expenseRecordDetail.setExemptBillMitigate(exemptBillCostDetail);
                    expenseRecordDetail.setExemptedAmt(expenseRecordDetail.getExemptedAmt().add(exemptBillCostDetail));
                    expenseRecordDetail.setExemptionAmt(expenseRecordDetail.getExemptionAmt().add(exemptBillCostDetail));
                    expenseRecordDetail.setRemainingAmt(expenseRecordDetail.getRemainingAmt().subtract(exemptBillCostDetail));
                    basicExpenseRecordDetailService.updateById(expenseRecordDetail);
                    break;
                }
            }
            for (BasicPenaltyInterest penaltyInterest : penaltyInterestList) {
                if (exemptBillCostInterest.compareTo(penaltyInterest.getOverdueAmt()) >= 0) {
                    exemptBillCostInterest = exemptBillCostInterest.subtract(penaltyInterest.getOverdueAmt());
                    //合同每期罚息明细表冲抵
                    penaltyInterest.setExemptBillMitigate(penaltyInterest.getOverdueAmt());
                    penaltyInterest.setExemptedAmt(penaltyInterest.getExemptedAmt().add(penaltyInterest.getOverdueAmt()));
                    penaltyInterest.setRealExemptionAmt(penaltyInterest.getRealExemptionAmt().add(penaltyInterest.getOverdueAmt()));
                    penaltyInterest.setOverdueAmt(BigDecimal.ZERO);
                    penaltyInterest.setStatus(ExpenseStatusEnum.settle);
                    basicPenaltyInterestService.updateById(penaltyInterest);
                } else {
                    //合同每期罚息明细表冲抵
                    penaltyInterest.setExemptBillMitigate(exemptBillCostInterest);
                    penaltyInterest.setExemptedAmt(penaltyInterest.getExemptedAmt().add(exemptBillCostInterest));
                    penaltyInterest.setRealExemptionAmt(penaltyInterest.getRealExemptionAmt().add(exemptBillCostInterest));
                    penaltyInterest.setOverdueAmt(penaltyInterest.getOverdueAmt().subtract(exemptBillCostInterest));
                    basicPenaltyInterestService.updateById(penaltyInterest);
                    break;
                }
            }
        }
        return IResponse.success("删除提前终止费用成功");
    }

    @ApiOperation(value = "豁免单费用冲抵撤销")
    @PostMapping("/delExemptBillMitigate")
    @Transactional(rollbackFor = Exception.class)
    public IResponse<Boolean> delExemptBillMitigate(@RequestBody StaySettleVo vo) {
        List<BasicExpenseRecord> expenseRecordList = basicExpenseRecordService.list(Wrappers.<BasicExpenseRecord>lambdaQuery()
                .eq(BasicExpenseRecord::getContractNo, vo.getContractNo()));
        List<BasicExpenseRecordDetail> expenseRecordDetailList = basicExpenseRecordDetailService.list(Wrappers.<BasicExpenseRecordDetail>lambdaQuery()
                .eq(BasicExpenseRecordDetail::getContractNo, vo.getContractNo()));
        List<BasicPenaltyInterest> penaltyInterestList = basicPenaltyInterestService.list(Wrappers.<BasicPenaltyInterest>lambdaQuery()
                .eq(BasicPenaltyInterest::getContractNo, vo.getContractNo()).orderByAsc(BasicPenaltyInterest::getTermNo));
        for (BasicExpenseRecord expenseRecord : expenseRecordList) {
            if (expenseRecord.getExemptBillMitigate().compareTo(BigDecimal.ZERO) > 0) {
                //合同费用记录表冲抵撤销
                expenseRecord.setExemptedAmt(expenseRecord.getExemptedAmt().subtract(expenseRecord.getExemptBillMitigate()));
                expenseRecord.setExemptionAmt(expenseRecord.getExemptionAmt().subtract(expenseRecord.getExemptBillMitigate()));
                expenseRecord.setRemainingAmt(expenseRecord.getRemainingAmt().add(expenseRecord.getExemptBillMitigate()));
                expenseRecord.setStatus(ExpenseStatusEnum.unsettle);
                expenseRecord.setExemptBillMitigate(BigDecimal.ZERO);
                basicExpenseRecordService.updateById(expenseRecord);
            }
        }
        for (BasicExpenseRecordDetail expenseRecordDetail : expenseRecordDetailList) {
            if (expenseRecordDetail.getExemptBillMitigate().compareTo(BigDecimal.ZERO) > 0) {
                //合同费用记录明细表冲抵撤销
                expenseRecordDetail.setExemptedAmt(expenseRecordDetail.getExemptedAmt().subtract(expenseRecordDetail.getExemptBillMitigate()));
                expenseRecordDetail.setExemptionAmt(expenseRecordDetail.getExemptionAmt().subtract(expenseRecordDetail.getExemptBillMitigate()));
                expenseRecordDetail.setRemainingAmt(expenseRecordDetail.getRemainingAmt().add(expenseRecordDetail.getExemptBillMitigate()));
                expenseRecordDetail.setStatus(ExpenseStatusEnum.unsettle);
                expenseRecordDetail.setExemptBillMitigate(BigDecimal.ZERO);
                basicExpenseRecordDetailService.updateById(expenseRecordDetail);
            }
        }
        for (BasicPenaltyInterest penaltyInterest : penaltyInterestList) {
            if (penaltyInterest.getExemptBillMitigate().compareTo(BigDecimal.ZERO) > 0) {
                //合同每期罚息明细表冲抵撤销
                penaltyInterest.setExemptedAmt(penaltyInterest.getExemptedAmt().subtract(penaltyInterest.getExemptBillMitigate()));
                penaltyInterest.setRealExemptionAmt(penaltyInterest.getRealExemptionAmt().subtract(penaltyInterest.getExemptBillMitigate()));
                penaltyInterest.setOverdueAmt(penaltyInterest.getOverdueAmt().add(penaltyInterest.getExemptBillMitigate()));
                penaltyInterest.setStatus(ExpenseStatusEnum.unsettle);
                penaltyInterest.setExemptBillMitigate(BigDecimal.ZERO);
                basicPenaltyInterestService.updateById(penaltyInterest);
            }
        }
        return IResponse.success("删除提前终止费用成功");
    }
}
